/**
 * 
 */
package tw.miku.model;

import java.nio.charset.CharacterCodingException;
import java.util.Collection;
import java.util.concurrent.ConcurrentHashMap;

import org.apache.mina.core.buffer.IoBuffer;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;

import tw.miku.protocol.codec.room.RemoveRoomResponsePack;
import tw.miku.protocol.codec.user.UserExitRoomResponsePack;
import tw.miku.protocol.codec.user.UserOfflineResponsePack;
import tw.miku.util.BufferUtility;

/**
 * @author imo
 * 
 */
public class Group
{
	private int id;
	private String name;

	private final ConcurrentHashMap<Integer, Room> rooms;
	private final ConcurrentHashMap<Long, User> users;

	/**
	 * 
	 */
	public Group()
	{
		rooms = new ConcurrentHashMap<>();
		users = new ConcurrentHashMap<>();
	}

	public int getId()
	{
		return id;
	}

	public void setId(int id)
	{
		this.id = id;
	}

	private String getName()
	{
		return name;
	}

	private void setName(String name)
	{
		this.name = name;
	}

	public void addRoom(Room room)
	{
		room.setGroup(this);
		rooms.put(room.getId(), room);
	}

	public Room getRoom(int roomId)
	{
		return rooms.get(roomId);
	}

	public void removeRoom(int roomId) throws CharacterCodingException
	{
		Room room = rooms.remove(roomId);
		// room.setGroup(null);
		room.dispose();

		RemoveRoomResponsePack pack = new RemoveRoomResponsePack();
		pack.roomId = roomId;
		this.sendToAllUser(pack.encode(), User.STATUS_LOBBY);

	}

	public void addUser(User user)
	{
		users.put(user.getId(), user);
	}

	public User getUser(long userId)
	{
		if (users.containsKey(userId))
		{
			return users.get(userId);
		}
		return null;
	}

	public Boolean containUser(String name)
	{
		Collection<User> us = users.values();
		for (User user : us)
		{
			if (user.getName().equals(name))
			{
				return true;
			}
		}
		return false;
	}

	public void removeUser(long userId) throws CharacterCodingException
	{
		UserOfflineResponsePack pack = new UserOfflineResponsePack();
		pack.userId = (int) userId;

		User user = users.remove(userId);
		Room room = user.getRoom();
		if (null != room)
		{
			room.removeUser(user);
			if (room.getUserCount() > 0)
			{
				UserExitRoomResponsePack exitPack = new UserExitRoomResponsePack();
				exitPack.userId = (int) userId;
				room.send(exitPack.encode());
			}
			else
			{
				this.removeRoom(room.getId());
			}
		}
		// user.setGroup(null);
		user.dispose();
		sendToAllUser(pack.encode(), User.STATUS_LOBBY);

	}

	public void sendToAllUser(Object message, int status)
	{
		Collection<User> us = users.values();
		for (User user : us)
		{
			if (0 != (user.getStatus() & status))
			{
				if (message instanceof IoBuffer)
				{
					user.send(BufferUtility.clone((IoBuffer) message));
				}
				else
				{
					user.send(message);
				}
			}
		}

	}

	public void sendToAllUser(Object message)
	{
		Collection<User> us = users.values();

		for (User user : us)
		{
			if (message instanceof IoBuffer)
			{
				user.send(BufferUtility.clone((IoBuffer) message));
			}
			else
			{
				user.send(message);
			}
		}

	}

	public void sendToAllRoom(Object message)
	{
		Collection<Room> rs = rooms.values();
		for (Room room : rs)
		{
			room.send(message);
		}
	}

	public Collection<Room> getRooms()
	{
		return rooms.values();
	}

	public Collection<User> getUsers()
	{
		return users.values();
	}

	public IoBuffer getRoomsInfo() throws CharacterCodingException
	{
		Collection<Room> allRooms = rooms.values();
		IoBuffer buff = BufferUtility.newInstance();
		BufferUtility.writeArray(buff, allRooms);
		buff.flip();
		return buff;
	}

	public IoBuffer getUsersInfo() throws CharacterCodingException
	{
		Collection<User> allUsers = users.values();
		IoBuffer buff = BufferUtility.newInstance();
		BufferUtility.writeArray(buff, allUsers);
		buff.flip();
		return buff;
	}

	public Element getRoomsXmlInfo()
	{
		Element element = DocumentHelper.createElement("rs");
		Collection<Room> rs = rooms.values();
		for (Room room : rs)
		{
			element.add(room.getXmlInfo());
		}
		return element;
	}

	public Element getUsersXmlInfo()
	{
		Element element = DocumentHelper.createElement("us");
		Collection<User> us = users.values();
		for (User user : us)
		{
			element.add(user.getXmlInfo());
		}
		return element;
	}

}
